#include "mainwindow.h"
#include "./ui_mainwindow.h"

MainWindow::MainWindow(QWidget* parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow), state(false), isAnimating(false)
{
    ui->setupUi(this);
    //初始化
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            s[i][j] = 0;
        }
    }
    button = new QPushButton("开始游戏", this);
    button->setGeometry(60, 400, 200, 50);
    connect(button, SIGNAL(clicked()), this, SLOT(slotStart()));
    animTimer = new QTimer(this);
    connect(animTimer, &QTimer::timeout, this, [this]() {
        bool allDone = true;
        for (auto& anim : animations) {
            anim.progress += 0.2;
            if (anim.progress < 1.0) allDone = false;
        }
        if (allDone) {
            animTimer->stop();
            isAnimating = false;
            animations.clear();
            myRand(); // 动画结束后生成新数字
            update();
        }
        else {
            update();
        }
        });
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::paintEvent(QPaintEvent*)
{
    QPainter p(this);
    p.setBrush(Qt::blue);
    p.setFont(QFont("微软雅黑", 20, 700, false));
    QString strscore;
    p.drawText(QPoint(20, 60), "分数:" + QString::number(score));
    //画格子
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            p.setPen(Qt::transparent);
            if (s[i][j] == 0) {
                p.setBrush(Qt::gray);
                p.drawRect(i * 60 + 40, j * 60 + 120, 55, 55);
            }
            else if (s[i][j] == 2) {
                p.setBrush(Qt::red);
                p.drawRect(i * 60 + 40, j * 60 + 120, 55, 55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑", 10, 700, false));
                p.drawText(QRectF(i * 60 + 40, j * 60 + 120, 55, 55), QString::number(2), QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j] == 4) {
                p.setBrush(Qt::darkRed);
                p.drawRect(i * 60 + 40, j * 60 + 120, 55, 55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑", 10, 700, false));
                p.drawText(QRectF(i * 60 + 40, j * 60 + 120, 55, 55), QString::number(4), QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j] == 8) {
                p.setBrush(Qt::green);
                p.drawRect(i * 60 + 40, j * 60 + 120, 55, 55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑", 10, 700, false));
                p.drawText(QRectF(i * 60 + 40, j * 60 + 120, 55, 55), QString::number(8), QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j] == 16) {
                p.setBrush(Qt::darkGreen);
                p.drawRect(i * 60 + 40, j * 60 + 120, 55, 55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑", 10, 700, false));
                p.drawText(QRectF(i * 60 + 40, j * 60 + 120, 55, 55), QString::number(16), QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j] == 32) {
                p.setBrush(Qt::yellow);
                p.drawRect(i * 60 + 40, j * 60 + 120, 55, 55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑", 10, 700, false));
                p.drawText(QRectF(i * 60 + 40, j * 60 + 120, 55, 55), QString::number(32), QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j] == 64) {
                p.setBrush(Qt::darkYellow);
                p.drawRect(i * 60 + 40, j * 60 + 120, 55, 55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑", 10, 700, false));
                p.drawText(QRectF(i * 60 + 40, j * 60 + 120, 55, 55), QString::number(64), QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j] == 128) {
                p.setBrush(Qt::cyan);
                p.drawRect(i * 60 + 40, j * 60 + 120, 55, 55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑", 10, 700, false));
                p.drawText(QRectF(i * 60 + 40, j * 60 + 120, 55, 55), QString::number(128), QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j] == 256) {
                p.setBrush(Qt::darkCyan);
                p.drawRect(i * 60 + 40, j * 60 + 120, 55, 55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑", 10, 700, false));
                p.drawText(QRectF(i * 60 + 40, j * 60 + 120, 55, 55), QString::number(256), QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j] == 512) {
                p.setBrush(Qt::magenta);
                p.drawRect(i * 60 + 40, j * 60 + 120, 55, 55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑", 10, 700, false));
                p.drawText(QRectF(i * 60 + 40, j * 60 + 120, 55, 55), QString::number(512), QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j] == 1024) {
                p.setBrush(Qt::darkMagenta);
                p.drawRect(i * 60 + 40, j * 60 + 120, 55, 55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑", 10, 700, false));
                p.drawText(QRectF(i * 60 + 40, j * 60 + 120, 55, 55), QString::number(1024), QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j] == 2048) {
                p.setBrush(Qt::blue);
                p.drawRect(i * 60 + 40, j * 60 + 120, 55, 55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑", 10, 700, false));
                p.drawText(QRectF(i * 60 + 40, j * 60 + 120, 55, 55), QString::number(2048), QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j] == 4096) {
                p.setBrush(Qt::darkBlue);
                p.drawRect(i * 60 + 40, j * 60 + 120, 55, 55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑", 10, 700, false));
                p.drawText(QRectF(i * 60 + 40, j * 60 + 120, 55, 55), QString::number(4096), QTextOption(Qt::AlignCenter));
            }
            else {
                p.setBrush(Qt::red);
                p.drawRect(i * 60 + 40, j * 60 + 120, 55, 55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑", 10, 700, false));
                p.drawText(QRectF(i * 60 + 40, j * 60 + 120, 55, 55), QString::number(s[i][j]), QTextOption(Qt::AlignCenter));
            }
        }
    }
    for (const auto& anim : animations) {
        qreal x = anim.startPos.x() + (anim.endPos.x() - anim.startPos.x()) * anim.progress;
        qreal y = anim.startPos.y() + (anim.endPos.y() - anim.startPos.y()) * anim.progress;

   
        if (anim.value == 2) p.setBrush(Qt::red);
  

        p.drawRect(x, y, 55, 55);
        p.drawText(QRectF(x, y, 55, 55), QString::number(anim.value), QTextOption(Qt::AlignCenter));
    }


    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            bool isAnimated = false;
            for (const auto& anim : animations) {
                if (anim.endPos == QPointF(i * 60 + 40, j * 60 + 120)) isAnimated = true;
            }
            if (!isAnimated && s[i][j] != 0) {
        
            }
        }
    }
}

void MainWindow::keyPressEvent(QKeyEvent* event)
{
    if (!state || isAnimating) return;
    if (!state) {
        return;
    }
    switch (event->key()) {
    case Qt::Key_W:
        PressUp();
        break;
    case Qt::Key_S:
        PressDown();
        break;
    case Qt::Key_A:
        PressLeft();
        break;
    case Qt::Key_D:
        PressRight();
        break;
    default:
        return;
    }
    myRand();
    update();
}
void MainWindow::slotStart() {
    QMessageBox::about(this, "游戏规则", "WASD控制方块上下左右移动");
    score = 0;
    // 清空数组
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            s[i][j] = 0;
        }
    }
    button->setText("重新游戏");
    // 生成两个初始的2
    int randi1 = QRandomGenerator::global()->bounded(4);
    int randj1 = QRandomGenerator::global()->bounded(4);
    int randi2, randj2;
    do {
        randi2 = QRandomGenerator::global()->bounded(4);
        randj2 = QRandomGenerator::global()->bounded(4);
    } while (randi1 == randi2 && randj1 == randj2);
    s[randi1][randj1] = 2;
    s[randi2][randj2] = 2;
    state = true;
    update();
}
void MainWindow::PressUp() {
    if (isAnimating) return;
    bool moved = false;
    animations.clear();

    int temp[4][4];
    memcpy(temp, s, sizeof(temp));


    for (int i = 0; i < 4; i++) {
        int writePos = 0;
        for (int j = 0; j < 4; j++) {
            if (temp[i][j] != 0) {
                if (j != writePos) {
      
                    BlockAnimation anim;
                    anim.startPos = QPointF(i * 60 + 40, j * 60 + 120);
                    anim.endPos = QPointF(i * 60 + 40, writePos * 60 + 120);
                    anim.value = temp[i][j];
                    anim.progress = 0.0;
                    anim.merged = false;
                    animations.append(anim);
                    s[i][writePos] = temp[i][j];
                    s[i][j] = 0;
                    moved = true;
                }
                writePos++;
            }
        }
    }


    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 3; j++) {
            if (s[i][j] == s[i][j + 1] && s[i][j] != 0) {
         
                BlockAnimation animMerge;
                animMerge.startPos = QPointF(i * 60 + 40, (j + 1) * 60 + 120);
                animMerge.endPos = QPointF(i * 60 + 40, j * 60 + 120);
                animMerge.value = s[i][j] * 2;
                animMerge.progress = 0.0;
                animMerge.merged = true;
                animations.append(animMerge);

                s[i][j] *= 2;
                score += s[i][j];
                s[i][j + 1] = 0;
                moved = true;

                for (int k = j + 1; k < 3; k++) {
                    s[i][k] = s[i][k + 1];
                    s[i][k + 1] = 0;
                    BlockAnimation animMove;
                    animMove.startPos = QPointF(i * 60 + 40, (k + 1) * 60 + 120);
                    animMove.endPos = QPointF(i * 60 + 40, k * 60 + 120);
                    animMove.value = s[i][k];
                    animMove.progress = 0.0;
                    animations.append(animMove);
                }
            }
        }
    }

    if (moved) {
        isAnimating = true;
        animTimer->start(16);
    }
    update();
}
void MainWindow::PressDown() {
    if (isAnimating) return;
    bool moved = false;
    animations.clear();

    int temp[4][4];
    memcpy(temp, s, sizeof(temp));

 
    for (int i = 0; i < 4; i++) {
        int writePos = 3;
        for (int j = 3; j >= 0; j--) {
            if (temp[i][j] != 0) {
                if (j != writePos) {
           
                    BlockAnimation anim;
                    anim.startPos = QPointF(i * 60 + 40, j * 60 + 120);
                    anim.endPos = QPointF(i * 60 + 40, writePos * 60 + 120);
                    anim.value = temp[i][j];
                    anim.progress = 0.0;
                    anim.merged = false;
                    animations.append(anim);
                    s[i][writePos] = temp[i][j];
                    s[i][j] = 0;
                    moved = true;
                }
                writePos--;
            }
        }
    }

  
    for (int i = 0; i < 4; i++) {
        for (int j = 3; j > 0; j--) {
            if (s[i][j] == s[i][j - 1] && s[i][j] != 0) {
         
                BlockAnimation animMerge;
                animMerge.startPos = QPointF(i * 60 + 40, (j - 1) * 60 + 120);
                animMerge.endPos = QPointF(i * 60 + 40, j * 60 + 120);
                animMerge.value = s[i][j] * 2;
                animMerge.progress = 0.0;
                animMerge.merged = true;
                animations.append(animMerge);

                s[i][j] *= 2;
                score += s[i][j];
                s[i][j - 1] = 0;
                moved = true;

           
                for (int k = j - 1; k > 0; k--) {
                    s[i][k] = s[i][k - 1];
                    s[i][k - 1] = 0;
                    BlockAnimation animMove;
                    animMove.startPos = QPointF(i * 60 + 40, (k - 1) * 60 + 120);
                    animMove.endPos = QPointF(i * 60 + 40, k * 60 + 120);
                    animMove.value = s[i][k];
                    animMove.progress = 0.0;
                    animations.append(animMove);
                }
            }
        }
    }

    if (moved) {
        isAnimating = true;
        animTimer->start(16);
    }
    update();
}
void MainWindow::PressLeft() {
    if (isAnimating) return;
    bool moved = false;
    animations.clear();

    int temp[4][4];
    memcpy(temp, s, sizeof(temp));

 
    for (int j = 0; j < 4; j++) {
        int writePos = 0;
        for (int i = 0; i < 4; i++) {
            if (temp[i][j] != 0) {
                if (i != writePos) {
               
                    BlockAnimation anim;
                    anim.startPos = QPointF(i * 60 + 40, j * 60 + 120);
                    anim.endPos = QPointF(writePos * 60 + 40, j * 60 + 120);
                    anim.value = temp[i][j];
                    anim.progress = 0.0;
                    anim.merged = false;
                    animations.append(anim);
                    s[writePos][j] = temp[i][j];
                    s[i][j] = 0;
                    moved = true;
                }
                writePos++;
            }
        }
    }

 
    for (int j = 0; j < 4; j++) {
        for (int i = 0; i < 3; i++) {
            if (s[i][j] == s[i + 1][j] && s[i][j] != 0) {
              
                BlockAnimation animMerge;
                animMerge.startPos = QPointF((i + 1) * 60 + 40, j * 60 + 120);
                animMerge.endPos = QPointF(i * 60 + 40, j * 60 + 120);
                animMerge.value = s[i][j] * 2;
                animMerge.progress = 0.0;
                animMerge.merged = true;
                animations.append(animMerge);

                s[i][j] *= 2;
                score += s[i][j];
                s[i + 1][j] = 0;
                moved = true;

             
                for (int k = i + 1; k < 3; k++) {
                    s[k][j] = s[k + 1][j];
                    s[k + 1][j] = 0;
                    BlockAnimation animMove;
                    animMove.startPos = QPointF((k + 1) * 60 + 40, j * 60 + 120);
                    animMove.endPos = QPointF(k * 60 + 40, j * 60 + 120);
                    animMove.value = s[k][j];
                    animMove.progress = 0.0;
                    animations.append(animMove);
                }
            }
        }
    }

    if (moved) {
        isAnimating = true;
        animTimer->start(16);
    }
    update();
}
void MainWindow::PressRight() {
    if (isAnimating) return;
    bool moved = false;
    animations.clear();

    int temp[4][4];
    memcpy(temp, s, sizeof(temp));


    for (int j = 0; j < 4; j++) {
        int writePos = 3;
        for (int i = 3; i >= 0; i--) {
            if (temp[i][j] != 0) {
                if (i != writePos) {
                
                    BlockAnimation anim;
                    anim.startPos = QPointF(i * 60 + 40, j * 60 + 120);
                    anim.endPos = QPointF(writePos * 60 + 40, j * 60 + 120);
                    anim.value = temp[i][j];
                    anim.progress = 0.0;
                    anim.merged = false;
                    animations.append(anim);
                    s[writePos][j] = temp[i][j];
                    s[i][j] = 0;
                    moved = true;
                }
                writePos--;
            }
        }
    }

    for (int j = 0; j < 4; j++) {
        for (int i = 3; i > 0; i--) {
            if (s[i][j] == s[i - 1][j] && s[i][j] != 0) {
    
                BlockAnimation animMerge;
                animMerge.startPos = QPointF((i - 1) * 60 + 40, j * 60 + 120);
                animMerge.endPos = QPointF(i * 60 + 40, j * 60 + 120);
                animMerge.value = s[i][j] * 2;
                animMerge.progress = 0.0;
                animMerge.merged = true;
                animations.append(animMerge);

                s[i][j] *= 2;
                score += s[i][j];
                s[i - 1][j] = 0;
                moved = true;

         
                for (int k = i - 1; k > 0; k--) {
                    s[k][j] = s[k - 1][j];
                    s[k - 1][j] = 0;
                    BlockAnimation animMove;
                    animMove.startPos = QPointF((k - 1) * 60 + 40, j * 60 + 120);
                    animMove.endPos = QPointF(k * 60 + 40, j * 60 + 120);
                    animMove.value = s[k][j];
                    animMove.progress = 0.0;
                    animations.append(animMove);
                }
            }
        }
    }

    if (moved) {
        isAnimating = true;
        animTimer->start(16);
    }
    update();
}

void MainWindow::myRand()
{
    //找空格子
    int i = 0;
    int j = 0;
    struct Ns n[16];
    int ni = 0;
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            if (s[i][j] == 0) {
                n[ni].i = i;
                n[ni].j = j;
                ni++;
            }
        }
    }
    if (ni == 0) {
        bool canMove = false;
        // 检查行和列是否有合并可能
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 3; j++) {
                if (s[i][j] == s[i][j + 1]) canMove = true;
            }
        }
        for (int j = 0; j < 4; j++) {
            for (int i = 0; i < 3; i++) {
                if (s[i][j] == s[i + 1][j]) canMove = true;
            }
        }
        if (!canMove) {
            QMessageBox::about(this, "游戏结束", "分数为：" + QString::number(score));
            state = false;
        }
        return;
    }
    int rand = QRandomGenerator::global()->bounded(ni);
    s[n[rand].i][n[rand].j] = 2;
}
